#include "../src/polytomousrasch.c"

#include <assert.h>
#include <stdio.h>

typedef struct _PolytomousRaschTestDatum PolytomousRaschTestDatum;
struct _PolytomousRaschTestDatum 
{
  struct
    {
      unsigned int  x;
      float        beta;
      float        tau[5];
    }                           input;

  struct
    {
      float    p;
      float    dpdbeta;
      float    dpdtau[5];
    }                           output;
};

static void
test_polytomous_rasch (void)
{
  PolytomousRaschTestDatum data[] = 
    {{{2, 2.85184, {4.23409, 3.15809, 3.42229, 0.274914,  2.64144}}, {-3.2169, -1.23422, {-0.216881, -0.271321, 0.6886,  0.665945, 0.367873}}}, {{3,  0.934076, {3.88088, 1.83653, 2.38437, 2.45947,  0.783123}}, {-5.37757,  2.88832, {-0.924944, -0.973511, -0.993208, 0.00217332,  0.00116852}}}, {{5,  2.94301, {3.4922, 2.87697, 1.01064, 0.23491, 4.68447}}, {-1.9854,  1.00032, {-0.0122618, -0.019342, -0.0269055, -0.0791385,  -0.862674}}}, {{4,  0.69553, {3.42446, 2.05343, 4.28133, 2.2911, 0.419203}}, {-9.34772,  3.90647, {-0.923561, -0.983859, -0.999368, -0.999798,  0.000114907}}}, {{0,  4.20159, {0.0472417, 4.13301, 1.99691, 3.92667,  2.4058}}, {-8.77532, -4.61122, {0.999846, 0.990002, 0.979461,  0.883874, 0.758042}}}, {{3,  3.19893, {3.11603, 2.09015, 0.0214371, 0.73946,  2.3329}}, {-3.70327, -1.65643, {-0.000312014, -0.000650998,  -0.00167835, 0.973679, 0.685392}}}, {{0,  4.14713, {1.52923, 2.86249, 1.32226, 3.91223,  1.84476}}, {-9.43459, -4.7655, {0.99992, 0.998825, 0.994867,  0.928142, 0.843749}}}, {{0,  2.16696, {2.8978, 1.85879, 2.56343, 4.87587,  2.4786}}, {-0.966406, -1.2705, {0.619553, 0.436365, 0.187058,  0.0193508, 0.0081799}}}, {{3,  2.65721, {2.51619, 0.742855, 0.481687, 3.73053,  0.110386}}, {-1.76664, -1.51767, {-0.00248489, -0.0053461,  -0.0247524, 0.804341, 0.745914}}}, {{4,  2.54392, {2.36566, 1.64038, 0.0889486, 1.80446,  0.032755}}, {-2.62959, -0.840381, {-0.00100193, -0.00219938,  -0.00515506, -0.0395773, 0.888315}}}};

  for (unsigned int i = 0; i < sizeof (data) / sizeof (data[0]); ++i)
    {
      float dpdbeta;
      float dpdtau[5];

#define taufunc(_k) data[i].input.tau[_k]
      float p = log_polytomous_rasch (data[i].input.x,
                                      data[i].input.beta,
                                      taufunc,
                                      5,
                                      dpdbeta,
                                      dpdtau);
#undef taufunc

      assert (      fabs (p - data[i].output.p) 
                 <= 1e-4 * (1 + fabs (p) + fabs (data[i].output.p))
              || (fprintf (stderr, "fail: %g != %g\n", p, data[i].output.p),
                  0));

      assert (      fabs (dpdbeta - data[i].output.dpdbeta) 
                 <= 1e-4 * (1 + fabs (dpdbeta) + fabs (data[i].output.dpdbeta))
              || (fprintf (stderr, "fail: %g != %g\n", dpdbeta, data[i].output.dpdbeta),
                  0));

      for (unsigned int k = 0; k < 5; ++k)
        {
          assert (      fabs (dpdtau[k] - data[i].output.dpdtau[k]) 
                     <= 1e-4 * (1 + fabs (dpdtau[k]) + fabs (data[i].output.dpdtau[k]))
                  || (fprintf (stderr, "fail: %g != %g\n", dpdtau[k], data[i].output.dpdtau[k]),
                      0));
        }
    }
}

int 
main (void)
{
  test_polytomous_rasch ();

  return 0;
}
